package com.csaba.connector.model;

import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.TreeMap;
import java.util.logging.Logger;

import com.csaba.util.I18N;
import com.csaba.util.LoggerHelper;

/**
 * Root of all modell class. This class supports storing arbitrary values coming from the server.
 * <p> Normally modell classes defining there own properties, together with setter and getter methods
 * which are used for the business logic of the Csaba framework (for exampel account number or available
 * balance for Account objects). But usually the bank's providing more information, that can be stored as 
 * "RemoteProperties" through methods provided by this class. In this way the customer gets the maximum
 * information from the bank servers that is available on the public interfaces, although only the normal
 * properties of the modell classes are used in the framework.
 * <p>Remote properties are name-value pairs, where the name is a single String (for example "overdraft.limit")
 *  and the value is an Object (String, Date, Amount, etc...). As the names are not user friendly 
 *  names but codes, or system names, this object supports localization for property names. 
 *  For more information see {@link #getLocalizedName(String)}.
 * @author Gabe
 *
 */
public abstract class AbstractRemoteObject
{
	private final static Logger logger = LoggerHelper.getDefaultLogger();

	private final NavigableMap<String, Object> remoteProperty = new TreeMap<String, Object>();

	public void setRemoteProperty( final String name, final Object value )
	{
		if ( value == null )
		{
			logger.fine("Empty value cannot be set: id = " + name); //$NON-NLS-1$
			return;
		}
		remoteProperty.put(name, value);
	}

	public boolean isRemotePropertySet( final String field )
	{
		return remoteProperty.containsKey(field);
	}

	public Object getRemoteProperty( final String field )
	{
		if ( remoteProperty.containsKey(field) )
			return remoteProperty.get(field);

		throw new IllegalArgumentException("Unsupported native field: " + field);
	}

	public Object removeRemoteProperty( final String field )
	{
		if ( remoteProperty.containsKey(field) )
			return remoteProperty.remove(field);

		throw new IllegalArgumentException("Unsupported native field: " + field);
	}

	/**
	 * FIXME update java doc, as I18N class is introduced
	 * Store localization string for each package. The resource bundle should be located in the same 
	 * package where the object model can be found. In case of missing resources the internal name
	 * or the property is provided back.<br>
	 * The resource file name should be <code>localization.properties</code>, and the content should
	 * account to the requirements of <code>java.util.ResourceBundle</code>.<br>
	 * The resource may contain translation per Entity bases, or generic description. For exmaple:
	 * <pre>
	 * account.number = Account number
	 * HisotryItem.account.number = Source account
	 * </pre>
	 * 
	 * @see AbstractRemoteObject.getLocalizedName()
	 */
	public String getLocalizedName( final String propertyName )
	{
		return I18N.getString(this, propertyName);
	}

	public String[] getRemotePropertyNames()
	{
		final NavigableSet<String> keys = remoteProperty.navigableKeySet();
		return keys.toArray(new String[keys.size()]);
	}
}
